﻿using System;
using System.Collections.Generic;
using System.Linq;
using RssReader.Common;
using RssReader.FeedProvider;
using RssReader.Feeds;
using Windows.ApplicationModel.Search;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Item = RssReader.FeedProvider.Item;


namespace RssReader
{
    // TODO: Edit the manifest to enable searching
    //
    // The package manifest could not be automatically updated.  Open the package manifest
    // file and ensure that support for activation for searching is enabled.
    /// <summary>
    /// This page displays search results when a global search is directed to this application.
    /// </summary>
    public sealed partial class SearchResultsPage : LayoutAwarePage
    {
        /// <summary>
        /// Feed Items
        /// </summary>
        private Feed _feed;
        private IList<Item> _allItems;
        private readonly CategoryHelper _categoryHelper = new CategoryHelper();
        public static SearchResultsPage Current;

        /// <summary>
        /// Records the value of the active Window's Content property when the search started.
        /// </summary>
        private static Type _previousContent;

        private string _keyword;
        static private Dictionary<string, object> _sessionState = new Dictionary<string, object>();

        static public Dictionary<string, object> Session_state
        {
            get { return _sessionState; }
        }
        public SearchResultsPage()
        {
            InitializeComponent();
            NavigationCacheMode = NavigationCacheMode.Disabled;
        }

        /// <summary>
        /// Populates the page with content passed during navigation.  Any saved state is also
        /// provided when recreating a page from a prior session.
        /// </summary>
        /// <param name="navigationParameter">The parameter value passed to
        /// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested.
        /// </param>
        /// <param name="pageState">A dictionary of state preserved by this page during an earlier
        /// session.  This will be null the first time a page is visited.</param>
        protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
        {
            // Unpack the two values passed in the parameter object: query text and previous
            layoutRoot.Background = new SolidColorBrush(App.ARGBColor);

            ring.IsActive = true;

            const string pageStateKey = "searchResults";


            var frameState = SuspensionManager.SessionState;

            if (navigationParameter != null)
            {
                frameState[pageStateKey] = navigationParameter;
            }
            if (frameState != null && frameState.ContainsKey(pageStateKey)) navigationParameter = frameState[pageStateKey];

            var tuple = (Tuple<string, Type>)navigationParameter;

            var searchQuery = tuple.Item1;

            var frame = tuple.Item2;
            _previousContent = frame;
            if (!string.IsNullOrEmpty(searchQuery)) Process_search(searchQuery);
        }

        internal void Search_results_page_query_submitted(SearchPane sender, SearchPaneQuerySubmittedEventArgs args)
        {
            Process_search(args.QueryText);
        }

        internal async void Process_search(string searchQuery)
        {
            var searchResult = await _categoryHelper.Search_all_blog_posts(searchQuery);
            bounds.Text = Fix_item_height_for_current_screen_resolution();
            DefaultViewModel["QueryText"] = '\u201c' + searchQuery + '\u201d';

            DefaultViewModel["Results"] = searchResult;

            ring.IsActive = false;

            if (searchResult.Count == 0)
            {
                resultsGridScrollViewer.Visibility = snappedPanel.Visibility = Visibility.Collapsed;
                NoResults.Visibility = Visibility.Visible;
            }
        }

        /// <summary>
        /// Invoked when the back button is pressed.
        /// </summary>
        /// <param name="sender">The Button instance representing the back button.</param>
        /// <param name="e">Event data describing how the button was clicked.</param>
        protected override void GoBack(object sender, RoutedEventArgs e)
        {
            // Return the application to the state it was in before search results were requested

            if (_previousContent == null) _previousContent = typeof(ItemsPage);

            var rootFrame = new Frame();
            rootFrame.Navigate(_previousContent);

            // Place the frame in the current Window and ensure that it is active
            Window.Current.Content = rootFrame;
        }

        /// <summary>
        /// Invoked when a filter is selected using the ComboBox in snapped view state.
        /// </summary>
        /// <param name="sender">The ComboBox instance.</param>
        /// <param name="e">Event data describing how the selected filter was changed.</param>
        private void Filter_selection_changed(object sender, SelectionChangedEventArgs e)
        {
            var selectedFilter = e.AddedItems.FirstOrDefault() as Filter;
            if (selectedFilter != null)
            {
                selectedFilter.Active = true;

                if (_feed != null && _keyword.Length > 2)
                {
                    List<Item> searchResult = (from item in _allItems
                                               where
                                                   item.Title.ToLower().Contains(_keyword.ToLower().Substring(1, _keyword.Length - 2)) ||
                                                   item.Description.ToLower().Contains(_keyword.ToLower().Substring(1, _keyword.Length - 2))
                                               select item).ToList();

                    DefaultViewModel["Results"] = searchResult;
                }
            }

            ring.IsActive = false;
        }

        /// <summary>
        /// Invoked when a filter is selected using a RadioButton when not snapped.
        /// </summary>
        /// <param name="sender">The selected RadioButton instance.</param>
        /// <param name="e">Event data describing how the RadioButton was selected.</param>
        private void Filter_checked(object sender, RoutedEventArgs e)
        {
            // Mirror the change into the CollectionViewSource used by the corresponding ComboBox
            // to ensure that the change is reflected when snapped
            if (filtersViewSource.View != null)
            {
                var frameworkElement = sender as FrameworkElement;
                if (frameworkElement != null)
                {
                    object filter = frameworkElement.DataContext;
                    filtersViewSource.View.MoveCurrentTo(filter);
                }
            }
        }

        private void Item_view_item_click(object sender, ItemClickEventArgs e)
        {
            var itemDetailsViewHelper = new ItemDetailsViewHelper().Get_selected_item_and_show_item_details_view(e, App.ItemsKeyString, Window.Current.Content);
            this.Frame.Navigate(typeof(ItemDetailPage), itemDetailsViewHelper);
        }

        #region Nested type: Filter

        /// <summary>
        /// View model describing one of the filters available for viewing search results.
        /// </summary>
        private sealed class Filter : BindableBase
        {
            private bool _active;
            private int _count;
            private String _name;

            public Filter(String name, int count, bool active = false)
            {
                Name = name;
                Count = count;
                Active = active;
            }

            public String Name
            {
                get { return _name; }
                set { if (SetProperty(ref _name, value)) OnPropertyChanged("Description"); }
            }

            public int Count
            {
                get { return _count; }
                set { if (SetProperty(ref _count, value)) OnPropertyChanged("Description"); }
            }

            public bool Active
            {
                get { return _active; }
                set { SetProperty(ref _active, value); }
            }

            public String Description
            {
                get { return String.Format("{0} ({1})", _name, _count); }
            }

            public override String ToString()
            {
                return Description;
            }
        }

        #endregion
    }
}